librerias
Bases de letras filtradas por idioma
# lyrics = mongo(collection = "lyrics", db = "spotify_dm" )
# df_lyrics <- lyrics$find('{}')
#
# write.csv(df_lyrics, "data/df_lyrics.csv")
df_lyrics <- read.csv("data/df_lyrics.csv") %>%
select(-X)
df_lyrics_unicas <- df_lyrics %>%
distinct(artist_name, track_name, lyrics)
#filtro de idioma
spa_lyrics = df_lyrics_unicas[textcat(df_lyrics_unicas$lyrics)=="spanish",]
spa_lyrics
en_lyrics = df_lyrics_unicas[textcat(df_lyrics_unicas$lyrics) %in% c("english", "scots"),]
en_lyrics
#chequeo cantidad de canciones por idioma
100*(nrow(en_lyrics) + nrow(spa_lyrics))/nrow(df_lyrics_unicas)
[1] 89.86784
# tabla contingencia de idiomas
idiomas = textcat(df_lyrics_unicas$lyrics)
sort(table(idiomas), decreasing = T)
idiomas
english scots spanish german middle_frisian catalan portuguese french
528 527 169 46 37 22 8 7
italian breton manx frisian rumantsch turkish
6 5 3 2 1 1
limpieza español
inspect(corpus.pro[1])
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘inspect’ for signature ‘"SimpleCorpus"’
limpieza ingles
head(en_lyrics$lyrics, 1)
[1] "look good together reason watch night long yeah know will turn heads forever tonight gonna show walking watch whole room change baby baby play blame confidenceoh blame measurements shut shit sight right dripping finesse make sense dripping finesse know know dripping finesse make sense dripping finesse know know now slow baby love way feels grind yeah connection magnetic floor nothing can stop us tonight walking watch whole room change baby baby play blame confidenceoh blame measurements shut shit sight right dripping finesse make sense dripping finesse know know dripping finesse make sense dripping finesse know know fellas grab ladies lady fine tell one one life woo ladies grab fellas let right right one like mind ow yeah got going got going feel good us ayy yeah got going got going yeah girl got going yeah got going got going hey feel good us ayy feels good yeah got going got going dripping finesse dripping make sense dripping finesse know know dripping finesse baby make sense dripping finesse know know yeah know got going yeah got going got going feel good us ayy yeah got going got going know know yeah got going got going girl got feel good us ayy yeah got going got going know know"
Explicit
Español
#Diccionario español
malas_palabras_1 <- read_csv("data/malas_palabras.txt",
col_names = FALSE)
malas_palabras_2 <- read_csv("data/malas_palabras_translate.txt",
col_names = FALSE)
malas_palabras_3 <- read_csv("data/malas_palabras_wiki.txt",
col_names = FALSE) %>%
select(X1)
malas_palabras_4 <- read_csv("data/palabras_profanas_es.txt",
col_names = FALSE)
malas_palabras <- rbind(malas_palabras_1, malas_palabras_2,
malas_palabras_3, malas_palabras_4)
#Función para limpiar.
text_cleaning_esp = function(txt, stop=FALSE){
txt = sub('^.+?\\[.*?\\]',"", txt) #ok
txt = sub("More on Genius.*","", txt)
txt = gsub('\\[.*?\\]', '', txt)
txt = gsub("\\n"," ", txt)
txt = gsub("[()]", " ", txt)
txt = tolower(txt)
# txt = decontracted(txt)
txt = gsub("\\W+\\b", " ", txt)
txt = gsub("\\d", " ", txt)
txt = str_trim(txt)
# txt = stri_trans_general(txt, "Latin-ASCII")
return(txt)
}
malas_palabras$limpias = text_cleaning(malas_palabras$X1)
malas_palabras
malas_palabras %>% filter(startsWith(limpias, "g"))
frecuencia de términos
# Dataframe con frecuencia de terminos (de rows)
dtm_to_freq <- TermDocumentMatrix(corpus.pro, control = list(weighting = "weightTf"))
matriz_td_to_freq <- as.matrix(dtm_to_freq)
freq_term <- sort(rowSums(matriz_td_to_freq), decreasing=TRUE )
df_freq <- data.frame(termino = names(freq_term), frecuencia=freq_term)
row.names(df_freq) <- NULL
head(df_freq)
## Graficos de terminos
N=15
barplot(df_freq[1:N,]$frecuencia, las = 2, names.arg = df_freq[1:N,]$termino,
col ="lightblue", main ="Palabras más frecuentes",
ylab = "Frecuencia de palabras", ylim = c(0, max(df_freq$frecuencia)+300))
topK = head(df_freq, 100)
# Visualización de los resultados
# Nube de Etiquetas
library("wordcloud")
library("RColorBrewer")
par(bg="grey30") # Fijamos el fondo en color gris
set.seed(1234)
wordcloud(words = topK$termino, freq = topK$frecuencia, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(4, "Dark2"))
LS0tDQp0aXRsZTogImx5cmljcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgbGlicmVyaWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkocmVzaGFwZSkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KG1vbmdvbGl0ZSkNCmxpYnJhcnkodGV4dGNhdCkNCmxpYnJhcnkodG0pDQpsaWJyYXJ5KHNlbnRpbWVudHIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGFydWxlcykNCmBgYA0KDQoNCiMgQmFzZXMgZGUgbGV0cmFzIGZpbHRyYWRhcyBwb3IgaWRpb21hDQpgYGB7cn0NCiMgbHlyaWNzID0gbW9uZ28oY29sbGVjdGlvbiA9ICJseXJpY3MiLCBkYiA9ICJzcG90aWZ5X2RtIiApDQojIGRmX2x5cmljcyA8LSBseXJpY3MkZmluZCgne30nKQ0KIyANCiMgd3JpdGUuY3N2KGRmX2x5cmljcywgImRhdGEvZGZfbHlyaWNzLmNzdiIpDQoNCmRmX2x5cmljcyA8LSByZWFkLmNzdigiZGF0YS9kZl9seXJpY3MuY3N2IikgJT4lIA0KICBzZWxlY3QoLVgpDQoNCmRmX2x5cmljc191bmljYXMgPC0gZGZfbHlyaWNzICU+JSANCiAgZGlzdGluY3QoYXJ0aXN0X25hbWUsIHRyYWNrX25hbWUsIGx5cmljcykNCg0KDQojZmlsdHJvIGRlIGlkaW9tYQ0Kc3BhX2x5cmljcyA9IGRmX2x5cmljc191bmljYXNbdGV4dGNhdChkZl9seXJpY3NfdW5pY2FzJGx5cmljcyk9PSJzcGFuaXNoIixdDQpzcGFfbHlyaWNzDQoNCmVuX2x5cmljcyA9IGRmX2x5cmljc191bmljYXNbdGV4dGNhdChkZl9seXJpY3NfdW5pY2FzJGx5cmljcykgJWluJSBjKCJlbmdsaXNoIiwgInNjb3RzIiksXQ0KZW5fbHlyaWNzDQoNCiNjaGVxdWVvIGNhbnRpZGFkIGRlIGNhbmNpb25lcyBwb3IgaWRpb21hDQoxMDAqKG5yb3coZW5fbHlyaWNzKSArIG5yb3coc3BhX2x5cmljcykpL25yb3coZGZfbHlyaWNzX3VuaWNhcykNCg0KIyB0YWJsYSBjb250aW5nZW5jaWEgZGUgaWRpb21hcw0KaWRpb21hcyA9IHRleHRjYXQoZGZfbHlyaWNzX3VuaWNhcyRseXJpY3MpDQojIHNvcnQodGFibGUoaWRpb21hcyksIGRlY3JlYXNpbmcgPSBUKQ0KDQpgYGANCg0KIyBsaW1waWV6YSBlc3Bhw7FvbA0KYGBge3J9DQojIGNvbWVudGFyIHkgZGVzY29tZW50YXIgc2Vnw7puIHNlIGVsaWphIHVuIGRhdGFmcmFtZSB1IG90cm8NCiMgZGZfbHlyaWNzX3NlbGVjY2lvbmFkbyA9IGRmX2x5cmljc191bmljYXMNCmRmX2x5cmljc19zZWxlY2Npb25hZG8gPSBlbl9seXJpY3MNCg0KY29ycHVzID0gQ29ycHVzKFZlY3RvclNvdXJjZShlbmMydXRmOChkZl9seXJpY3Nfc2VsZWNjaW9uYWRvJGx5cmljcykpKQ0KDQojIEVsaW1pbmFtb3MgZXNwYWNpb3MNCmNvcnB1cy5wcm8gPC0gdG1fbWFwKGNvcnB1cywgc3RyaXBXaGl0ZXNwYWNlKQ0KaW5zcGVjdChjb3JwdXMucHJvWzFdKQ0KDQojIEVsaW1pbm8gdG9kbyBsbyBxdWUgYXBhcmVjZSBhbnRlcyBkZWwgcHJpbWVyIFtdDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCBjb250ZW50X3RyYW5zZm9ybWVyKA0KICBmdW5jdGlvbih4KSBzdWIoJ14uKz9cXFsuKj9cXF0nLCIiLCB4KSkpDQojIGluc3BlY3QoY29ycHVzLnByb1sxXSkNCg0KIyBFbGltaW5vIGxhcyBhY2xhcmFjaW9uZXMgZW4gbGFzIGNhbmNpb25lcywgcG9yIGVqZW1wbG86DQojIFtWZXJzbyAxOiBMdWlzIEZvbnNpICYgRGFkZHkgWWFua2VlXQ0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcigNCiAgZnVuY3Rpb24oeCkgZ3N1YignXFxbLio/XFxdJywgJycsIHgpKSkNCg0KIyBFbGltaW5vIHRvZG8gbG8gcXVlIGFwYXJlY2UgbHVlZ28gZGUgJ01vcmUgb24gR2VuaXVzJw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbih4KSBnc3ViKCJNb3JlIG9uIEdlbml1cy4qIiwiIiwgeCkpKQ0KDQojIENvbnZlcnRpbW9zIGVsIHRleHRvIGEgbWluw7pzY3VsYXMNCmNvcnB1cy5wcm8gPC0gdG1fbWFwKGNvcnB1cy5wcm8sIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQoNCiMgcmVtb3ZlbW9zIG7Dum1lcm9zDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZW1vdmVOdW1iZXJzKQ0KDQojIFBvZGVtb3MgYWdyZWdhciBwYWxhYnJhcyBhIGxhcyBzdG9wd29yZHMNCiMgbXlfc3RvcHdvcmRzIDwtIGFwcGVuZChzdG9wd29yZHMoInNwYW5pc2giKSwgJ3BhbGFicmEnKQ0KbXlfc3RvcHdvcmRzIDwtIGFwcGVuZChzdG9wd29yZHMoImVuZ2xpc2giKSwgYygneWVhaCcsICJhaW50IiwgImdldCIsICJnb3QiKSkNCg0KIyBSZW1vdmVtb3MgcGFsYWJyYXMgdmFjaWFzIA0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQ0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIG15X3N0b3B3b3JkcykNCiMgY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIHN0b3B3b3Jkcygic3BhbmlzaCIpKQ0KIyBpbnNwZWN0KGNvcnB1cy5wcm9bMV0pDQoNCg0KIyBSZW1vdmVtb3MgcHVudHVhY2lvbmVzDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZW1vdmVQdW5jdHVhdGlvbikNCg0KIyBSZW1vdmVtb3MgdG9kbyBsbyBxdWUgbm8gZXMgYWxmYW51bcOpcmljbw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbih4KSBzdHJfcmVwbGFjZV9hbGwoeCwgIltbOnB1bmN0Ol1dIiwgIiAiKSkpDQoNCiMgRW4gdG1fbWFwIHBvZGVtb3MgdXRpbGl6YXIgZnVuY2lvbmVzIHByb3ANCmxpYnJhcnkoc3RyaW5naSkNCnJlcGxhY2VBY2VudG9zIDwtIGZ1bmN0aW9uKHgpIHtzdHJpX3RyYW5zX2dlbmVyYWwoeCwgIkxhdGluLUFTQ0lJIil9DQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZXBsYWNlQWNlbnRvcykNCg0KIyBFbGltaW5hbW9zIGVzcGFjaW9zIHF1ZSBzZSB2YW4gZ2VuZXJhbmRvIGNvbiBsb3MgcmVlbXBsYXpvcw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgc3RyaXBXaGl0ZXNwYWNlKQ0KYGBgDQoNCiMgbGltcGllemEgaW5nbGVzDQpgYGB7cn0NCiNmdW5jaW9uZXMNCiNmdW5jaW9uIHBhcmEgY29ycmVnaXIgcGFsYWJyYXMNCmRlY29udHJhY3RlZCA9IGZ1bmN0aW9uKHR4dCl7DQogIHR4dCA9IGdzdWIoIndvbid0IiwgIndpbGwgbm90IiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXCdzIiwgIiBpcyIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwndCIsICIgbm90IiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXCdsbCIsICIgd2lsbCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwnbSIsICIgYW0iLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJ3JlIiwgIiBhcmUiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJ2QiLCAiIGhhZCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwndmUiLCAiIGhhdmUiLCB0eHQpDQogIHR4dCA9IGdzdWIoImNvdWxkbiIsICJjb3VsZCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiZG9uIiwgImRvIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJkb2VzbiIsICJkb2VzIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJpc24iLCAiaXMiLCB0eHQpDQogIHR4dCA9IGdzdWIoIm11c3RuIiwgIm11c3QiLCB0eHQpDQogIHR4dCA9IGdzdWIoInNob3VsZG4iLCAic2hvdWxkIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJ3YXNuIiwgIndhcyIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwnY2F1c2UiLCAiIGJlY2F1c2UiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJyIsICJnIiwgdHh0KQ0KICByZXR1cm4odHh0KQ0KfQ0KDQoNCiNGdW5jacOzbiBwYXJhIGxpbXBpYXIuIA0KdGV4dF9jbGVhbmluZyA9IGZ1bmN0aW9uKHR4dCwgc3RvcD1GQUxTRSwgbGFuZ3VhZ2Upew0KICANCiAgdHh0ID0gc3ViKCdeLis/XFxbLio/XFxdJywiIiwgdHh0KSAjb2sNCiAgdHh0ID0gc3ViKCJNb3JlIG9uIEdlbml1cy4qIiwiIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCdcXFsuKj9cXF0nLCAnJywgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXG4iLCIgIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJbKCldIiwgIiAiLCB0eHQpDQogIHR4dCA9IHRvbG93ZXIodHh0KQ0KICB0eHQgPSBkZWNvbnRyYWN0ZWQodHh0KQ0KICB0eHQgPSBnc3ViKCJcXFcrXFxiIiwgIiAiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcZCIsICIgIiwgdHh0KQ0KICANCiAgc3RvcHdvcmRzX3JlZ2V4ID0gcGFzdGUoc3RvcHdvcmRzKCdlbicpLCBjb2xsYXBzZSA9ICdcXGJ8XFxiJykNCiAgc3RvcHdvcmRzX3JlZ2V4ID0gcGFzdGUwKCdcXGInLCBzdG9wd29yZHNfcmVnZXgsICdcXGInKQ0KICB0eHQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwodHh0LCBzdG9wd29yZHNfcmVnZXgsICcnKQ0KDQogIG15X3N0b3B3b3JkcyA8LSBjKCdvb2gnLCAneWVhaCcsICJhaW50IiwgImdldCIsICJnb3QiLCAiYXl5IikNCiAgdHh0ID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHR4dCwgbXlfc3RvcHdvcmRzLCAnJykNCiAgIA0KICB0eHQgPSBzdHJfdHJpbSh0eHQpDQogIHR4dCA9IGdzdWIoIlxcbiIsIiAiLCB0eHQpDQogIA0KICBpZihsYW5ndWFnZSA9PSAiZW4iKXsNCiAgICByZXR1cm4odHh0KQ0KICB9ZWxzZSBpZiAobGFuZ3VhZ2UgPT0gImVzIil7DQogICAgdHh0IDwtIGZ1bmN0aW9uKHgpIHtzdHJpX3RyYW5zX2dlbmVyYWwoeCwgIkxhdGluLUFTQ0lJIil9DQogICAgICByZXR1cm4odHh0KSANCiAgfWVsc2V7DQogICAgICAgIHJldHVybigiRmFsdGEgZGVmaW5pciBsZW5ndWFqZSIpDQogICAgICB9DQp9DQoNCiNmdW5jacOzbiBwYXJhIG9idGVuZXIgb3JhY2lvbmVzIGRlIHVuYSBzb2xhIHBhbGFicmEuIA0Kb25lX3dvcmRfc2V0ZW5jZXMgPSBmdW5jdGlvbih0eHQpew0KICByZXR1cm4oZ3N1YigiXFxXK1xcYiIsICIuICIsIHR4dCkpDQp9DQoNCiNsaW1waW8gbGFzIGxldHJhcyBlbiBpbmdsZXMNCmVuX2x5cmljcyRseXJpY3MgPSB0ZXh0X2NsZWFuaW5nKGVuX2x5cmljcyRseXJpY3MsIGxhbmd1YWdlID0gImVuIikNCg0KaGVhZChlbl9seXJpY3MkbHlyaWNzLCAxKQ0KDQoNCmBgYA0KDQoNCg0KIyBFeHBsaWNpdA0KIyMgRXNwYcOxb2wNCmBgYHtyfQ0KI0RpY2Npb25hcmlvIGVzcGHDsW9sDQptYWxhc19wYWxhYnJhc18xIDwtIHJlYWRfY3N2KCJkYXRhL21hbGFzX3BhbGFicmFzLnR4dCIsIA0KICAgIGNvbF9uYW1lcyA9IEZBTFNFKQ0KDQptYWxhc19wYWxhYnJhc18yIDwtIHJlYWRfY3N2KCJkYXRhL21hbGFzX3BhbGFicmFzX3RyYW5zbGF0ZS50eHQiLCANCiAgICBjb2xfbmFtZXMgPSBGQUxTRSkNCg0KbWFsYXNfcGFsYWJyYXNfMyA8LSByZWFkX2NzdigiZGF0YS9tYWxhc19wYWxhYnJhc193aWtpLnR4dCIsIA0KICAgIGNvbF9uYW1lcyA9IEZBTFNFKSAlPiUgDQogIHNlbGVjdChYMSkNCg0KbWFsYXNfcGFsYWJyYXNfNCA8LSByZWFkX2NzdigiZGF0YS9wYWxhYnJhc19wcm9mYW5hc19lcy50eHQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sX25hbWVzID0gRkFMU0UpDQoNCm1hbGFzX3BhbGFicmFzIDwtIHJiaW5kKG1hbGFzX3BhbGFicmFzXzEsIG1hbGFzX3BhbGFicmFzXzIsDQogICAgICAgICAgICAgICAgICAgICAgICBtYWxhc19wYWxhYnJhc18zLCBtYWxhc19wYWxhYnJhc180KQ0KDQoNCiNGdW5jacOzbiBwYXJhIGxpbXBpYXIuIA0KdGV4dF9jbGVhbmluZ19lc3AgPSBmdW5jdGlvbih0eHQsIHN0b3A9RkFMU0Upew0KICB0eHQgPSBzdWIoJ14uKz9cXFsuKj9cXF0nLCIiLCB0eHQpICNvaw0KICB0eHQgPSBzdWIoIk1vcmUgb24gR2VuaXVzLioiLCIiLCB0eHQpDQogIHR4dCA9IGdzdWIoJ1xcWy4qP1xcXScsICcnLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcbiIsIiAiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlsoKV0iLCAiICIsIHR4dCkNCiAgdHh0ID0gdG9sb3dlcih0eHQpDQogICMgdHh0ID0gZGVjb250cmFjdGVkKHR4dCkNCiAgdHh0ID0gZ3N1YigiXFxXK1xcYiIsICIgIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXGQiLCAiICIsIHR4dCkNCiAgdHh0ID0gc3RyX3RyaW0odHh0KQ0KICAjIHR4dCA9IHN0cmlfdHJhbnNfZ2VuZXJhbCh0eHQsICJMYXRpbi1BU0NJSSIpDQogIHJldHVybih0eHQpDQp9DQoNCg0KbWFsYXNfcGFsYWJyYXMkbGltcGlhcyA9IHRleHRfY2xlYW5pbmcobWFsYXNfcGFsYWJyYXMkWDEpDQptYWxhc19wYWxhYnJhcw0KDQptYWxhc19wYWxhYnJhcyAlPiUgZmlsdGVyKHN0YXJ0c1dpdGgobGltcGlhcywgImciKSkNCg0KYGBgDQoNCiMjIEluZ2zDqXMNCmBgYHtyfQ0KI0dlbmVybyBsaXN0YSBkZSBtYWxhcyBwYWxhYnJhcw0KYmFkX3dvcmRzIDwtIGMoKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV96YWNfYW5nZXIpKSkNCmJhZF93b3JkcyA8LSBhcHBlbmQoYmFkX3dvcmRzLCB1bmlxdWUodG9sb3dlcihsZXhpY29uOjpwcm9mYW5pdHlfYWx2YXJleikpKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV9hcnJfYmFkKSkpDQpiYWRfd29yZHMgPC0gYXBwZW5kKGJhZF93b3JkcywgdW5pcXVlKHRvbG93ZXIobGV4aWNvbjo6cHJvZmFuaXR5X3JhY2lzdCkpKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV9iYW5uZWQpKSkNCmJhZF93b3JkcyA8LSB1bmlxdWUoYmFkX3dvcmRzKQ0KDQpiaWdsb3UgPC0gcmVhZC5jc3YoImh0dHBzOi8vd3d3LmNzLmNtdS5lZHUvfmJpZ2xvdS9yZXNvdXJjZXMvYmFkLXdvcmRzLnR4dCIsIGhlYWRlcj1GQUxTRSwgY29sLm5hbWVzID0gYygid29yZHMiKSkNCg0KDQojRnVuY2nDs24gcGFyYSBvYnRlbmVyIHBhbGFicmFzIHByb2ZhbmFzIGRlIGNhZGEgbHlyaWMNCmdldF9wcm9mYW5pdGllcyA9IGZ1bmN0aW9uKHR4dCwgcHJvZmFuaXR5X2xzdCl7DQogICMgdHh0ID0gdGV4dF9jbGVhbmluZyh0eHQpDQogIHdvcmRzID0gYXMuZGF0YS5mcmFtZShzdHJzcGxpdCh0eHQsICJbIF0rIiksIGNvbC5uYW1lcyA9ICJ3b3JkcyIpDQogIHByb2Zhbl9kZiA9IHByb2Zhbml0eShnZXRfc2VudGVuY2VzKHdvcmRzKSwgcHJvZmFuaXR5X2xpc3QgPSBwcm9mYW5pdHlfbHN0KQ0KICBwcm9mYW5fd29yZHMgPSBwcm9mYW5fZGZbcHJvZmFuX2RmJHByb2Zhbml0eV9jb3VudCE9MCxdJHdvcmRzDQogIHZlY3RvciA9IGFzLnZlY3Rvcihwcm9mYW5fd29yZHMpDQogIGlmIChsZW5ndGgodmVjdG9yKT09MCl7DQogICAgcmV0dXJuKE5VTEwpDQogIH0NCiAgZWxzZXtyZXR1cm4oYXMudmVjdG9yKHByb2Zhbl93b3JkcykpDQogICAgfQ0KfQ0KDQoNCg0KZW5fbHlyaWNzJHByb2ZhYmVfYmlnbG91IDwtIGxhcHBseShlbl9seXJpY3MkbHlyaWNzLCAgZnVuY3Rpb24oeCkgZ2V0X3Byb2Zhbml0aWVzKHgsIGJpZ2xvdSR3b3JkcykpDQoNCmVuX2x5cmljcyAlPiUgDQogIG11dGF0ZShwcm9mYW5lX2JpZ2xvdSA9IHVubGlzdChnZXRfcHJvZmFuaXRpZXMobHlyaWNzLCBiaWdsb3Ukd29yZHMpKSkNCg0KZW5fbHlyaWNzJHByb2ZhYmVfYmlnbG91ID0gdW5saXN0KHN0cnNwbGl0KGVuX2x5cmljcyRwcm9mYWJlX2JpZ2xvdSwgc3BsaXQgPSAiICIpKQ0KDQplbl9seXJpY3MkcHJvZmFiZV9iYWR3b3JkcyA8LSBsYXBwbHkoZW5fbHlyaWNzJGx5cmljcywgZnVuY3Rpb24oeCkgZ2V0X3Byb2Zhbml0aWVzKHgsIGJhZF93b3JkcykpDQoNCnN0cihlbl9seXJpY3MpDQpoZWFkKGVuX2x5cmljcywxKQ0KDQplbl9seXJpY3MkcHJvZmFiZV9iaWdsb3VbM10NCg0KYGBgDQoNCg0KIyBtYXRyaXogdMOpcm1pbm8gZG9jdW1lbnRvDQpgYGB7cn0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIEdlbmVyYWNpw7NuIGRlIGxhIE1hdHLDrXogVMOpcm1pbm8tRG9jdW1lbnRvIGRlbCBjb3JwdXMgIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmNvcnB1cy5wcm8ydGRtIDwtIGZ1bmN0aW9uKGNvcnB1cywgcG9uZGVyYWNpb24sIG5fdGVybXMpew0KICAjY29ycHVzDQogIA0KICANCiAgI21hdHJpeiBURCANCiAgZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwdXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3Qod2VpZ2h0aW5nID0gcG9uZGVyYWNpb24pKQ0KICBtYXRyaXpfdGQgPC0gYXMubWF0cml4KGR0bSkNCiAgDQogIA0KICAjIENhbGN1bGFtb3MgbGEgZnJlY3VlbmNpYSBkZSBjYWRhIHTDqXJtaW5vIGVuIGVsIGNvcnB1cw0KICBmcmVxX3Rlcm0gPC0gaGVhZChzb3J0KHJvd1N1bXMobWF0cml6X3RkKSxkZWNyZWFzaW5nPVRSVUUpLCBuX3Rlcm1zKQ0KICANCiAgI21hdHJpeiB0cmFuc3B1ZXN0YSBkZSBsb3Mgbl90ZXJtcyBtYXMgZnJlY3VlbnRlcw0KICBtYXRyaXpfbmYgPC0gdChtYXRyaXpfdGRbc29ydChuYW1lcyhmcmVxX3Rlcm0pKSwgXSkNCiAgDQogICNwYXNhamUgYSBiaW5hcmlvDQogIG1hdHJpel9uZlttYXRyaXpfbmY+MF0gPC0gMQ0KICANCiAgcmV0dXJuKG1hdHJpel9uZikNCiAgDQogIH0NCiAgDQpjb3JwdXNfZW5nID0gQ29ycHVzKFZlY3RvclNvdXJjZShlbmMydXRmOChlbl9seXJpY3MkbHlyaWNzKSkpDQptYXRyaXogPC0gY29ycHVzLnBybzJ0ZG0oY29ycHVzID0gY29ycHVzX2VuZywgcG9uZGVyYWNpb249ICJ3ZWlnaHRUZiIsbl90ZXJtcz0gMTUwKQ0KDQpkaW0obWF0cml6KQ0KDQpkZl90bSA8LSBhcy5kYXRhLmZyYW1lKG1hdHJpeikNCmhlYWQoZGZfdG0sMikNCg0KIyMgSm9pbiBtYXRyaXogZGUgcGFsYWJyYXMgY29uIGFydGlzdGEgeSB0cmFjaw0KZGZfbHlfZmVhdCA8LSBjYmluZChkZl9seXJpY3Nfc2VsZWNjaW9uYWRvWy1jKDMpXSwgZGZfdG0pDQoNCm5yb3coZGZfdG0pDQpucm93KGRmX2x5cmljc19zZWxlY2Npb25hZG8pDQpucm93KGRmX2x5X2ZlYXQpDQoNCmZpbHRlciA8LSAhbmFtZXMoZGZfbHlfZmVhdCkgJWluJSBjKCJhcnRpc3RfbmFtZSIsICJ0cmFja19uYW1lIiApDQoNCmRmX2x5X2ZlYXRfb2sgPC0gZGZfbHlfZmVhdFssIGZpbHRlcl0NCiMgZGZfbHlfZmVhdF9vayA9IGRmX2x5X2ZlYXRfb2tbLCAtKHdoaWNoKGNvbFN1bXMoZGZfbHlfZmVhdF9vaykgPT0gMCkpXQ0KDQojIGNvbFN1bXMoZGZfbHlfZmVhdF9vaykNCg0KaGVhZChkZl9seV9mZWF0X29rLCAzKQ0KaGVhZChkZl9seV9mZWF0LCAzKQ0KDQoNCmRmX2x5X2ZlYXQkaWQgPSAxOm5yb3coZGZfbHlfZmVhdCkNCg0KZGZfbWVsdCA8LSByZXNoYXBlMjo6bWVsdChkYXRhID0gZGZfbHlfZmVhdFssMzpuY29sKGRmX2x5X2ZlYXQpXSwgaWQudmFycyA9IGMoImlkIikpICAlPiUNCiAgYXJyYW5nZShpZCkNCg0KZGZfbWVsdCA8LSBkZl9tZWx0W2RmX21lbHQkdmFsdWUgIT0gMCxdDQoNCmRmX21lbHRfdHh0IDwtIGRmX21lbHRbZGZfbWVsdCR2YWx1ZSA9PSAxLF0NCmRmX21lbHRfY2F0IDwtIGRmX21lbHRbZGZfbWVsdCR2YWx1ZSAhPSAxLF0NCg0KaGVhZChkZl9tZWx0X3R4dCApDQpkaW0oZGZfbWVsdF90eHQgKQ0KDQojZGVub21pbm8gYSBsb3MgdMOpcm1pbm9zIHByb2Zhbm9zDQpkZl9tZWx0X3R4dCA8LSBkZl9tZWx0X3R4dCAlPiUgDQogIG11dGF0ZSh2YXJpYWJsZSA9IGNhc2Vfd2hlbihhcy5jaGFyYWN0ZXIodmFyaWFibGUpICVpbiUgYmlnbG91JHdvcmRzIH4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJQUk9GXyIsIGFzLmNoYXJhY3Rlcih2YXJpYWJsZSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVCB+IHBhc3RlMCgiVEVSTV8iLCBhcy5jaGFyYWN0ZXIodmFyaWFibGUpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAgDQogICAgICAgICApDQoNCmRmX21lbHRfdHh0ICU+JSBmaWx0ZXIoc3RhcnRzV2l0aCh2YXJpYWJsZSwgIlBST0YiKSkNCg0KDQojIGRmX21lbHRfdHh0W2RmX21lbHRfdHh0JHZhcmlhYmxlICVpbiUgYmlnbG91JHdvcmRzLF0NCg0KDQpkZl9tZWx0X3R4dF90b19ydWxzIDwtIGRmX21lbHRfdHh0WywgLWMoMyldDQpuYW1lcyhkZl9tZWx0X3R4dF90b19ydWxzKSA8LSBjKCJpZCIsICJpdGVtIikNCg0Kd3JpdGUudGFibGUoZGZfbWVsdF90eHRfdG9fcnVscywgZmlsZT0iZGF0YS90cmFuc2FjY2lvbnNfbHlyaWNzX2ZlYXR1cmVzLnR4dCIsIHJvdy5uYW1lcyA9IEYpDQoNCiMgUmVnbGFzDQojIGNoZXF1ZWFyIG5hbidzDQpseXJpY3NfdHJhbnMgPC0gcmVhZC50cmFuc2FjdGlvbnMoImRhdGEvdHJhbnNhY2Npb25zX2x5cmljc19mZWF0dXJlcy50eHQiLCBmb3JtYXQgPSAic2luZ2xlIiwgY29scyA9IGMoMSwyKSkNCg0KYXJ1bGVzOjppbnNwZWN0KGhlYWQobHlyaWNzX3RyYW5zLCAzKSkNCg0Kc3VtbWFyeShseXJpY3NfdHJhbnMpDQpyZWdsYXMgPC0gYXByaW9yaShseXJpY3NfdHJhbnMsIHBhcmFtZXRlciA9IGxpc3Qoc3VwcG9ydD0wLjEsDQogICAgICAgICAgICAgICAgICAgIGNvbmZpZGVuY2UgPSAwLjUsIHRhcmdldCAgPSAicnVsZXMiICApKQ0KDQpyZWdsYXNfc3ViIDwtIHN1YnNldChyZWdsYXMsIHN1YnNldCA9IHJocyAlcGluJSAiUFJPRl8iKQ0KYXJ1bGVzOjppbnNwZWN0KGhlYWQoc29ydChyZWdsYXNfc3ViLCBieSA9ICJsaWZ0IiwgZGVjcmVhc2luZyA9IFQpLDUpKQ0KDQpgYGANCg0KDQoNCiMgZnJlY3VlbmNpYSBkZSB0w6lybWlub3MNCmBgYHtyfQ0KIyBEYXRhZnJhbWUgY29uIGZyZWN1ZW5jaWEgZGUgdGVybWlub3MgKGRlIHJvd3MpDQpkdG1fdG9fZnJlcSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycHVzLnBybywgY29udHJvbCA9IGxpc3Qod2VpZ2h0aW5nID0gICJ3ZWlnaHRUZiIpKQ0KbWF0cml6X3RkX3RvX2ZyZXEgPC0gYXMubWF0cml4KGR0bV90b19mcmVxKQ0KZnJlcV90ZXJtIDwtIHNvcnQocm93U3VtcyhtYXRyaXpfdGRfdG9fZnJlcSksIGRlY3JlYXNpbmc9VFJVRSApDQpkZl9mcmVxIDwtIGRhdGEuZnJhbWUodGVybWlubyA9IG5hbWVzKGZyZXFfdGVybSksIGZyZWN1ZW5jaWE9ZnJlcV90ZXJtKQ0Kcm93Lm5hbWVzKGRmX2ZyZXEpIDwtIE5VTEwNCmhlYWQoZGZfZnJlcSkNCg0KDQojIyBHcmFmaWNvcyBkZSB0ZXJtaW5vcw0KTj0xNQ0KYmFycGxvdChkZl9mcmVxWzE6TixdJGZyZWN1ZW5jaWEsIGxhcyA9IDIsIG5hbWVzLmFyZyA9IGRmX2ZyZXFbMTpOLF0kdGVybWlubywNCiAgICAgICAgY29sID0ibGlnaHRibHVlIiwgbWFpbiA9IlBhbGFicmFzIG3DoXMgZnJlY3VlbnRlcyIsDQogICAgICAgIHlsYWIgPSAiRnJlY3VlbmNpYSBkZSBwYWxhYnJhcyIsIHlsaW0gPSBjKDAsIG1heChkZl9mcmVxJGZyZWN1ZW5jaWEpKzMwMCkpDQoNCg0KdG9wSyA9IGhlYWQoZGZfZnJlcSwgMTAwKQ0KDQojIFZpc3VhbGl6YWNpw7NuIGRlIGxvcyByZXN1bHRhZG9zDQojIE51YmUgZGUgRXRpcXVldGFzDQpsaWJyYXJ5KCJ3b3JkY2xvdWQiKQ0KbGlicmFyeSgiUkNvbG9yQnJld2VyIikNCg0KcGFyKGJnPSJncmV5MzAiKSAjIEZpamFtb3MgZWwgZm9uZG8gZW4gY29sb3IgZ3Jpcw0KDQpzZXQuc2VlZCgxMjM0KQ0Kd29yZGNsb3VkKHdvcmRzID0gdG9wSyR0ZXJtaW5vLCBmcmVxID0gdG9wSyRmcmVjdWVuY2lhLCBtaW4uZnJlcSA9IDEsDQogICAgICAgICAgbWF4LndvcmRzPTIwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCByb3QucGVyPTAuMzUsIA0KICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDQsICJEYXJrMiIpKQ0KDQoNCg0KYGBgDQoNCg0K